home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
telecomm
/
zmdm.zoo
/
zm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-27
|
22KB
|
1,085 lines
/*
* ACKNOWLEDGEMENTS
*
* ZMDM was derived from rz/sz for Unix posted by
* Chuck Forsberg (...!tektronix!reed!omen!caf ). We
* thank him for his excellent code, and for giving
* us permission to use and distribute his code and
* documentation.
*
* Atari St version by:
* Jwahar Bammi
* bang: uunet!cadence!bammi
* domain: bammi@cadence.com
* GEnie: J.Bammi
* CIS: 71515,155
*/
/*
* Z M . C
* ZMODEM protocol primitives
* 05-24-89 Chuck Forsberg Omen Technology Inc
*
* Entry point Functions:
* zsbhdr(type, hdr) send binary header
* zshhdr(type, hdr) send hex header
* zgethdr(hdr, eflag) receive header - binary or hex
* zsdata(buf, len, frameend) send data
* zrdata(buf, len) receive data
* stohdr(pos) store position data in Txhdr
* long rclhdr(hdr) recover position offset from header
*
* This version implements ZMODEM Run Length Encoding, Comparision,
* and variable length headers. These features were not funded
* by the original Telenet development contract. This software,
* including these features, may be freely used for non
* commercial and educational purposes. This software may also
* be freely used to support file transfer operations to or from
* licensed Omen Technology products. Contact Omen Technology
* for licensing for other uses. Any programs which use part or
* all of this software must be provided in source form with this
* notice intact except by written permission from Omen
* Technology Incorporated.
*
* Omen Technology Inc FAX: 503-621-3745
* Post Office Box 4681
* Portland OR 97208
*
* Previous versions of this program (not containing the extensions
* listed above) remain in the public domain.
*
* This code is made available in the hope it will be useful,
* BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
* DAMAGES OF ANY KIND.
*
*/
#include "config.h"
#include "zmdm.h"
#include "common.h"
#ifndef CANFDX
#include "zmodem.h"
#endif
#define xsendline(X) sendline(X)
static char *badcrc = "Bad CRC";
static lastsent; /* Last char we sent */
static Not8bit; /* Seven bits seen on header */
static char *frametypes[] = {
"No Response to Error Correction Request", /* -4 */
"Carrier Lost", /* -3 */
"TIMEOUT", /* -2 */
"ERROR", /* -1 */
#define FTOFFSET 3
"ZRQINIT",
"ZRINIT",
"ZSINIT",
"ZACK",
"ZFILE",
"ZSKIP",
"ZNAK",
"ZABORT",
"ZFIN",
"ZRPOS",
"ZDATA",
"ZEOF",
"ZFERR",
"ZCRC",
"ZCHALLENGE",
"ZCOMPL",
"ZCAN",
"ZFREECNT",
"ZCOMMAND",
"ZSTDERR",
"xxxxx"
#define FRTYPES 22 /* Total number of frame types in this array */
/* not including psuedo negative entries */
};
#define flushmo flush_modem
/* Send ZMODEM binary header hdr of type type */
void zsbhdr(len, type, hdr)
int len, type;
register char *hdr;
{
register int n;
register unsigned short crc;
#ifndef DSZ
vfile2("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
frametypes[type+FTOFFSET], rclhdr(hdr));
#endif
if (type == ZDATA)
for (n = Znulls; --n >=0; )
xsendline(0);
xsendline(ZPAD); xsendline(ZDLE);
switch (Crc32t=Txfcs32) {
case 2:
zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
flushmo(); break;
case 1:
zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32); break;
default:
if (Usevhdrs) {
xsendline(ZVBIN);
zsendline(len);
}
else
xsendline(ZBIN);
zsendline(type);
crc = updcrc(type, 0);
for (n=len; --n >= 0; ++hdr) {
zsendline(*hdr);
crc = updcrc((0377& *hdr), crc);
}
crc = updcrc(0,updcrc(0,crc));
zsendline(crc>>8);
zsendline(crc);
}
if (type != ZDATA)
flushmo();
}
/* Send ZMODEM binary header hdr of type type */
void zsbh32(len, hdr, type, flavour)
int len, type, flavour;
register char *hdr;
{
register int n;
register unsigned long crc;
xsendline(flavour);
if (Usevhdrs)
zsendline(len);
zsendline(type);
crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
for (n=len; --n >= 0; ++hdr) {
crc = UPDC32((0377 & *hdr), crc);
zsendline(*hdr);
}
crc = ~crc;
for (n=4; --n >= 0;) {
zsendline((unsigned int)crc);
crc >>= 8;
}
}
/* Send ZMODEM HEX header hdr of type type */
void zshhdr(len, type, hdr)
int len, type;
register char *hdr;
{
register int n;
register unsigned int crc;
#ifndef DSZ
vfile2("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
frametypes[type+FTOFFSET], rclhdr(hdr));
#endif
sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
if (Usevhdrs) {
sendline(ZVHEX);
zputhex(len);
}
else
sendline(ZHEX);
zputhex(type);
Crc32t = 0;
crc = updcrc(type, 0);
for (n=len; --n >= 0; ++hdr) {
zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
}
crc = updcrc(0,updcrc(0,crc));
zputhex(crc>>8); zputhex(crc);
/* Make it printable on remote machine */
sendline(015); sendline(0212);
/*
* Uncork the remote in case a fake XOFF has stopped data flow
*/
if (type != ZFIN && type != ZACK)
sendline(021);
flushmo();
}
/*
* Send binary array buf of length length, with ending ZDLE sequence frameend
*/
static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
void zsdata(buf, length, frameend)
register char *buf;
int length, frameend;
{
register unsigned short crc;
#ifndef DSZ
vfile2("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
#endif
switch (Crc32t) {
case 1:
zsda32(buf, length, frameend); break;
case 2:
zsdar32(buf, length, frameend); break;
default:
crc = 0;
for (;--length >= 0; ++buf) {
zsendline(*buf); crc = updcrc((0377 & *buf), crc);
}
xsendline(ZDLE); xsendline(frameend);
crc = updcrc(frameend, crc);
crc = updcrc(0,updcrc(0,crc));
zsendline(crc>>8); zsendline(crc);
}
if (frameend == ZCRCW) {
xsendline(XON); flushmo();
}
}
void zsda32(buf, length, frameend)
int length, frameend;
register char *buf;
{
register int c;
register unsigned long crc;
crc = 0xFFFFFFFFL;
for (;--length >= 0; ++buf) {
c = *buf & 0377;
if (c & 0140)
xsendline(lastsent = c);
else
zsendline(c);
crc = UPDC32(c, crc);
}
xsendline(ZDLE); xsendline(frameend);
crc = UPDC32(frameend, crc);
crc = ~crc;
for (c=4; --c >= 0;) {
zsendline((unsigned int)crc); crc >>= 8;
}
}
/*
* Receive array buf of max length with ending ZDLE sequence
* and CRC. Returns the ending character or error code.
* NB: On errors may store length+1 bytes!
*/
int zrdata(buf, length)
register char *buf;
int length;
{
register int c;
register unsigned short crc;
register char *end;
register int d;
switch (Crc32r) {
case 1:
return zrdat32(buf, length);
case 2:
return zrdatr32(buf, length);
}
crc = Rxcount = 0; end = buf + length;
while (buf <= end) {
if ((c = zdlread()) & ~0377) {
crcfoo:
switch (c) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
crc = updcrc((d=c)&0377, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updcrc(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = updcrc(c, crc);
if (crc & 0xFFFF) {
log2(badcrc);
return ERROR;
}
Rxcount = length - (end - buf);
#ifndef DSZ
vfile2("zrdata: %d %s", Rxcount,
Zendnames[d-GOTCRCE&3]);
#endif
return d;
case GOTCAN:
log2("Sender Canceled");
return ZCAN;
case TIMEOUT:
log2("TIMEOUT");
return c;
default:
garbitch(); return c;
}
}
*buf++ = c;
crc = updcrc(c, crc);
}
#ifdef DSZ
garbitch();
#else
log2("Data subpacket too long");
#endif
return ERROR;
}
int zrdat32(buf, length)
register char *buf;
int length;
{
register int c;
register unsigned long crc;
register char *end;
register int d;
crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length;
while (buf <= end) {
if ((c = zdlread()) & ~0377) {
crcfoo:
switch (c) {
case GOTCRCE:
case GOTCRCG:
case GOTCRCQ:
case GOTCRCW:
d = c; c &= 0377;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if ((c = zdlread()) & ~0377)
goto crcfoo;
crc = UPDC32(c, crc);
if (crc != 0xDEBB20E3L) {
log2(badcrc);
return ERROR;
}
Rxcount =